home *** CD-ROM | disk | FTP | other *** search
- /** LISTING 2 ***** TERM.C *************************/
- #include <conio.h>
- #include <stdio.h>
- #include <time.h>
- #include <dos.h>
- #include "uart.h"
- #include "uartmacs.c"
-
- /* Set to 1 by dummy interrupt machine if
- correct interrupt during port presence test */
- static char g_got_int_flag;
-
- /* Base address of port being tested */
- static unsigned int g_port_base_address;
-
- /*****************************************************
- rc = Test_for_asynch_port (port_address, irq_level )
- int port_address - Base address of port to test
- for
- int irq_level - Interrupt level (3 - 7) that
- port is supposed to be on
- rc = 1 : Port check passes
- rc = -1: Port check fails or IRQ out of range
- *****************************************************/
-
- /* Enable stack probing for this function */
- #pragma check_stack(on)
- int Test_for_asynch_port( unsigned int port_address,
- unsigned int irq_level )
- {
- int mask_save;
- int new_mask;
- unsigned int interrupt_number;
- static char a_funcname[] =
- "Test_for_asynch_port: ";
- void (interrupt far * p_vec_saved)();
- time_t start_time;
- time_t time_now;
-
- /* Validate range of irq level */
- if ( (irq_level < 3) || ( irq_level > 7 ) )
- {
- fprintf(stderr,"%s bad irq level %u\n",
- a_funcname,irq_level);
- return(-1);
- }
-
- /* Clear flag - we haven't gotten a successful
- interrupt yet. */
- g_got_int_flag = 0;
-
- /* Save port address for interrupt routine */
- g_port_base_address = port_address;
-
- /* Make sure interrupt generation is disabled */
- outp(port_address+INTERRUPT_ENABLE_REGISTER,0x00);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Clear interrupt identification register */
- inp(port_address+INTERRUPT_IDENT_REGISTER);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Clear receive register. */
- inp(port_address+RECEIVE_REGISTER);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Clear line status interrupt */
- inp(port_address+LINE_STATUS_REGISTER);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Clear modem status interrupt */
- inp(port_address+MODEM_STATUS_REGISTER);
-
- /* Calculate interrupt number */
- interrupt_number = 0x08 + irq_level;
-
- /* Save current interrupt vector */
- p_vec_saved = _dos_getvect(interrupt_number);
-
- _disable(); /* disable interrupts */
-
- /* Latch test interrupt routine into vector */
- _dos_setvect(interrupt_number,
- Catch_asynch_test_interrupt);
-
- /* Save current 8259 state and enable this
- interrupt */
- mask_save = inp(R8259A_MASK);
- new_mask = ((int)
- ( 0xffff ^ ( 0x0001 << irq_level) )) &
- mask_save;
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Output new mask to 8259 interrupt controller */
- outp(R8259A_MASK,new_mask);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- _enable(); /* Enable interrupts */
-
- /* Activate OUT2 to enable interrupt generation by
- the UART */
- outp(port_address+MODEM_CONTROL_REGISTER,0x08);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Enable generation of THRE interrupt */
- outp(port_address+INTERRUPT_ENABLE_REGISTER,0x02);
-
-
- /* Save start time */
- time(&start_time);
-
- /* Loop until flag indicating receipt of interrupt
- has been set (up to 3 seconds) */
- while ( g_got_int_flag == 0 )
- {
- /* If more than 3 seconds have passed,
- stop waiting */
- time(&time_now);
- if ( (time_now - start_time) > 3)
- break;
- }
-
- /* Make sure interrupt generation is disabled */
- outp(port_address+INTERRUPT_ENABLE_REGISTER,0x00);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Deactivate OUT2 to disable interrupt generation
- by UART */
- outp(port_address+MODEM_CONTROL_REGISTER,0x00);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Clear interrupt identification register */
- inp(port_address+INTERRUPT_IDENT_REGISTER);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Clear receive register. */
- inp(port_address+RECEIVE_REGISTER);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Clear line status interrupt */
- inp(port_address+LINE_STATUS_REGISTER);
-
- /* Delay for port to catch up */
- IO_DELAY(3);
-
- /* Clear modem status interrupt */
- inp(port_address+MODEM_STATUS_REGISTER);
-
- _disable(); /* Disable interrupts */
-
- /* Restore 8259 state */
- outp(R8259A_MASK,mask_save);
-
- /* Restore interrupt vector */
- _dos_setvect(interrupt_number,p_vec_saved);
-
- _enable();
-
- if ( g_got_int_flag == 1)
- return(1);
- else
- return(-1);
- }
- /* Disable stack probing for interrupt catcher */
- #pragma check_stack(off)
- void interrupt far Catch_asynch_test_interrupt(void)
- {
- register int value_from_port;
-
- _disable(); /* Disable all interrupts */
-
- /* read port's interrupt identification register */
- value_from_port = inp(g_port_base_address+
- INTERRUPT_IDENT_REGISTER);
-
- if ( !(value_from_port & 0x01) )
- { /* There is an interrupt pending */
- if (value_from_port & 0x02)
- { /* interrupt for transmit holding
- register empty */
-
- /* Read the port's line status register and
- check for THRE just to double check */
- value_from_port = inp(g_port_base_address +
- LINE_STATUS_REGISTER);
- if ( value_from_port & 0x20 )
- /* We have succeeded! Set global
- flag. */
- g_got_int_flag = 1;
-
- }
- }
-
- /* Output End Of Interrupt to interrupt
- controller */
- outp(R8259A_CONTROL,0x20);
-
- /* Note - Interrupts are not re-enabled to ensure
- that the IRET will be executed before
- the next interrupt */
-
- return;
- }
-